Deep Learning

1. Deep learning 개요

1.1 Deep learning 모형

딥러닝 모형은 층을 여러 겹으로 쌓은 깊은 신경망 모형을 통칭한 것이다. 일반적으로 얕은 신경망에서 은닉층의 노드 개수를 늘리는 것보다 층별 노드 수는 적게 하고 깊이를 깊게 하는 것이 효과적인 것으로 알려져 있다. 또한 앞 단계의 은닉층은 저급한 수준의 특징(feature)을 추출해주고 뒤 단계로 갈수록 고급 수준으로 추상화된 특징을 추출해 줄 것으로 기대할 수 있다. 다양한 수준의 특징공간(feature space)에서 학습이 이루어지기 때문에 모형의 표현력이 분석 목적에 맞도록 적응하게 된다. 이러한 점은 기존 머신러닝 알고리즘에서 사용해 온 특징변수들이 hand-crafted인 점과 대비된다.

1.2 학습

딥러닝 모형을 함수 추정의 관점에서 보면 각 은닉층에 대응되는 비선형함수를 여러 겹으로 합성한 모형으로 이해할 수 있다. 각 비선형함수들은 독자적인 모수집합을 포함하고 있기 때문에 은닉층의 개수가 많아지면 그에 따라 학습해야 하는 모수의 개수가 급격히 증가하게 된다. 즉, 전체 모수를 동시에 갱신하는 알고리즘은 제대로 작동하기 어렵다. 각 은닉층별로 모수를 갱신하는 오차역전파(error back-propagation) 알고리즘이 좋은 대안이다.

2. Enhancing plans

2.1 데이터 preprocessing

숫자형 입력변수는 표준화해서 사용하는 것이 좋다. 기계학습에서는 정규화(normalization)라 부른다. 입력변수들이 서로 척도가 너무 다르면 가중치 값 역시 척도가 달라지게 되어 학습에 좋지 않은 영향을 끼칠 염려가 있다. 명목형(nominal) 입력변수는 one-hot 방식으로 코딩해 사용한다. 예를 들어 ABO 혈액형은 4비트로 확장해 입력한다. 즉, O형은 (1, 0, 0, 0), A형은 (0, 1, 0, 0), B형은 (0, 0, 1, 0), AB형은 (0, 0, 0, 1)으로 입력한다.

2.2 가중치 초기화

초기값을 모두 0으로 두면 학습이 이루지지 않는다. 보통 정규분포 또는 균일분포 난수를 이용하는데 둘 사이의 차이는 거의 없다. 다만, 어느 분포를 사용하든 산포 정도는 중요하다.

  • 균일분포 난수를 이용할 때: \(n_{\rm in}\)\(n_{\rm out}\) 을 앞 층의 노드 개수와 뒤 층의 노드 개수라 하면

    • LeCun 방법: \({\rm Unif}(-r, r)\). 단, \(r = \frac{1}{\sqrt{n_{\rm in}}}\)

    • Glorot 방법: \({\rm Unif}(-r, r)\). 단, \(r = \sqrt{\frac{6}{n_{\rm in}+n_{\rm out}}}\)

  • 정규분포 난수를 이용할 때

    • Xavier 방법: \(N(0, n_{\rm in}^{-1})\)

    • He 방법 (for ReLU): \(N(0, 2/n_{\rm in})\)

2.4 Regularization

학습데이터가 문제의 크기에 비해 작은 경우 학습알고리즘은 주어진 학습 데이터를 단순 ’암기’하는 상태가 되어 새로운 데이터에 대한 예측 성능이 떨어지게 되는데 이를 오버피팅 문제라 한다. 모형의 복잡도에 대한 벌점을 반영한 목적함수를 사용해 오버피팅 문제를 완화시킬 수 있다.

\[ J(\Theta) + \lambda\, \Omega({\boldsymbol\Theta}) \]

벌점항 \(\Omega({\boldsymbol\Theta})\)은 가중치의 값을 0에 가까워지도록 해 알고리즘의 모델 용량을 제어하는 역할을 하게 된다. 단, Bias 항은 regularize하지 않음에 유의하자. 벌점항에 어떤 norm을 사용하는가에 따라 효과가 조금 달라진다.

  • \({\mathcal L}_1\)-norm: sparse한 연결 구조 제공

  • \({\mathcal L}_2\)-norm: ridge. 분산 감소

2.5 Optimizers beyond SGD

Momentum

그래디언트에 섞이는 잡음을 모멘텀(속도) 벡터를 사용하여 스무딩해 수렴 속도를 개선하는 방법이다.

\[\begin{eqnarray*} & & {\mathbf v} \leftarrow \alpha {\mathbf v} - \rho \frac{\partial J}{\partial\Theta}\\ & & \Theta \leftarrow \Theta + {\mathbf v} \end{eqnarray*}\]

위 식에서 \({\mathbf v}\)은 이전 단계의 그래디언트 정보를 누적한 것이다. 초기치로는 영벡터 사용하면 된다. \(\alpha\)는 0과 1 사이의 값으로 정하는데, 1에 가까울수록 이전 그래디언트 정보에 많은 가중치를 주게 되어 \(\Theta\)가 그리는 궤적이 더 매끄러워진다. 보통 0.5, 0.9, 0.99를 사용한다.

Nesterov momentum

현재 \(\mathbf v\)값을 이용해 다음 이동할 곳을 예견(\(\tilde\Theta\))하고, 예견한 곳의 그래디언트를 사용하는 방법이다.

\[\begin{eqnarray*} & & \tilde\Theta = \Theta + \alpha{\mathbf v}\\ & & {\mathbf v} \leftarrow \alpha {\mathbf v} - \rho \frac{\partial J}{\partial\Theta}\Big|_{\tilde\Theta}\\ & & \Theta \leftarrow \Theta + {\mathbf v} \end{eqnarray*}\]

AdaGrad

가중치마다 다른 학습률을 적용하는 방식이다. 가중치별 그래디언트 크기의 누적값을 다음과 같은 방식으로 이용한다.

\[\begin{eqnarray*} & & {\mathbf r} \leftarrow {\mathbf r} + \frac{\partial J}{\partial\Theta}\odot\frac{\partial J}{\partial\Theta}\\ & & \Theta \leftarrow \Theta -\frac{\rho}{{\mathbf r} + \epsilon} \frac{\partial J}{\partial\Theta} \end{eqnarray*}\]

\({\mathbf r}\)의 초기치로 영벡터를 사용한다.

RMSProp

AdaGrad에서 \(\mathbf r\)을 업데이트 하는 방식을 수정한 버전이다.

\[ {\mathbf r} \leftarrow \alpha{\mathbf r} + (1-\alpha)\frac{\partial J}{\partial\Theta}\odot\frac{\partial J}{\partial\Theta} \]

갱신 과정에서 오래 전 그래디언트의 영향을 지수적으로 감쇄시키는 효과가 있다. \(\alpha\) 값으로 보통 0.9, 0.99, 0.999를 사용한다.

Adam

Momentum 방법과 RMSProp 방법을 결합한 방식이다.

\[\begin{eqnarray*} & & {\mathbf v} \leftarrow \alpha_1 {\mathbf v} - (1-\alpha_1)\frac{\partial J}{\partial\Theta}\\ & & {\mathbf v} \leftarrow \frac{1}{1-\alpha_1^{\rm iter}}{\mathbf v} \\ & & {\mathbf r} \leftarrow \alpha_2{\mathbf r} + (1-\alpha_2)\frac{\partial J}{\partial\Theta}\odot\frac{\partial J}{\partial\Theta}\\ & & {\mathbf r} \leftarrow \frac{1}{1-\alpha_2^{\rm iter}}{\mathbf r} \\ & & \Theta \leftarrow \Theta -\frac{\rho}{{\mathbf r} + \epsilon} \frac{\partial J}{\partial\Theta} \end{eqnarray*}\]




Which one?

절대적 기준은 없으며, 경험적으로 선택하면 된다. 다 잘 작동하는 편이다.

2.6 Dropout

각 학습 단계마다 랜덤하게 노드를 삭제하는 방식으로 일종의 regularization technique, 또는 앙상블 방법으로 이해할 수 있다. 계산속도가 획기적으로 빨라지며 오버피팅 문제를 완화시키는 효과가 있다. 예측 단계에서는 forward feed 시 은닉노드 값에 (1 - 드롭아웃비율)을 곱해 사용함에 유의해야 한다. 드롭아웃 비율로 0.5를 사용하면 무난하다고 알려져 있다.













2.7 Early stopping

매 반복마다 validation dataset을 이용해 성능을 확인하고, 연속으로 \(p\)번(참을성 인자) 이상 성능 향상이 없으면 멈추는 방식이다. 참을성 인자로 \(p\)회를 사용하되 수렴 조건 확인은 \(q\)-epoch 마다 확인하는 전략도 가능하다.



2.8 활성화함수

깊은 신경망에서 시그모이드 함수를 사용하는 경우 backpropagation 과정에서 소위 그래디언트 소멸(vanishing gradient) 문제가 발생한다. 이 때문에 가중치 갱신이 제대로 이루어지기 어렵고 결과적으로 학습이 잘 안 되는 문제가 생기게 된다.



ReLU 함수는 그래디언트 소멸 문제가 없으면서 음의 영역에서 미분이 0이 되어 regularization 효과를 기대할 수 있다. 0에서 함수값이 꺾이기 때문에 미분이 불가능한 문제를 해결하기 위한 ReLU의 변종들이 있으나 실제로 적용해보면 성능은 그닥 나오지 않는 편이다.

2.9 배치 정규화

공변량 시프트(covariate shift)란 각 은닉층의 값의 분포와 입력값의 분포가 심하게 달라짐에 따라 학습에 부정적 영향을 미치는 현상을 가리킨다. 입력값 뿐 아니라 각 층별로 은닉노드 값에 대해 표준화를 시행해 해결 가능하다. 미니배치 단위로 층별 표준화를 수행하게 되는데 다음과 같은 효과를 기대할 수 있다.

  • 가중치 초기값에 덜 민감해짐

  • 학습률을 크게 설정해 수렴 속도를 향상시킬 수 있음

  • 시그모이드 활성화함수를 사용한 깊은 신경망도 성능이 나옴

  • Regularization 효과가 있음

2.10 Data augmentation

비용을 적게 들이며 데이터의 양을 늘리는 방안을 통칭하는 말이다. 이미지 데이터의 경우 이동, 회전, 크기 변환 등을 활용한다.

2.11 Example: MNIST dataset

show_digit <- function(arr784, col = gray(1:12 / 12), ...) 
{
  image(matrix(as.matrix(arr784[-785]), nrow = 28)[, 28:1], 
        col = col, axes = FALSE, ...)
}

library(keras)

# To install the core Keras library + TensorFlow, 최초 한 번만 실행 
# install_keras() # 실행 전에 Anaconda for Python 3.x 설치해야 함 

mnist <- dataset_mnist()
x_train <- mnist$train$x
y_train <- mnist$train$y
x_test <- mnist$test$x
y_test <- mnist$test$y

# reshape
x_train <- array_reshape(x_train, c(nrow(x_train), 784))
x_test <- array_reshape(x_test, c(nrow(x_test), 784))
# rescale
x_train <- x_train / 255
x_test <- x_test / 255

y_train <- to_categorical(y_train, 10)
y_test <- to_categorical(y_test, 10)

model <- keras_model_sequential() 
model %>% 
  layer_dense(units = 256, activation = 'relu', input_shape = c(784)) %>% 
  layer_dropout(rate = 0.5) %>% 
  layer_dense(units = 128, activation = 'relu') %>%
  layer_dropout(rate = 0.3) %>%
  layer_dense(units = 10, activation = 'softmax')

summary(model)
Model: "sequential"
___________________________________________________________________________
Layer (type)                     Output Shape                  Param #     
===========================================================================
dense (Dense)                    (None, 256)                   200960      
___________________________________________________________________________
dropout (Dropout)                (None, 256)                   0           
___________________________________________________________________________
dense_1 (Dense)                  (None, 128)                   32896       
___________________________________________________________________________
dropout_1 (Dropout)              (None, 128)                   0           
___________________________________________________________________________
dense_2 (Dense)                  (None, 10)                    1290        
===========================================================================
Total params: 235,146
Trainable params: 235,146
Non-trainable params: 0
___________________________________________________________________________
model %>% compile(
  loss = 'categorical_crossentropy',
  optimizer = optimizer_rmsprop(),
  metrics = c('accuracy')
)

history <- model %>% fit(
  x_train, y_train, 
  epochs = 20, batch_size = 100, 
  validation_split = 0.2
)

plot(history)

model %>% evaluate(x_test, y_test)
$loss
[1] 0.1056855157

$acc
[1] 0.9803000093
Predicted <- model %>% predict_classes(x_test)
Actual <- as.integer(apply(y_test, 1, which.max) - 1)
table(Actual, Predicted)
      Predicted
Actual    0    1    2    3    4    5    6    7    8    9
     0  972    1    1    0    0    2    1    1    1    1
     1    0 1126    4    0    0    1    2    0    2    0
     2    3    1 1013    0    1    0    1    8    5    0
     3    0    0    5  984    0    7    0    7    4    3
     4    0    0    2    0  965    0    4    1    2    8
     5    2    0    0    4    1  873    5    2    4    1
     6    6    2    0    1    2    3  942    0    2    0
 [ reached getOption("max.print") -- omitted 3 rows ]
Right_cases <- (1:10000)[Predicted == Actual]
Wrong_cases <- (1:10000)[Predicted != Actual]

par(mfrow = c(1, 2))
show_digit(x_test[Right_cases[1],])
show_digit(x_test[Wrong_cases[1],])

Predicted[Right_cases[1]]
[1] 7
Actual[Right_cases[1]]
[1] 7
Predicted[Wrong_cases[1]]
[1] 9
Actual[Wrong_cases[1]]
[1] 4

3. Convolutional Neural Network

3.1 기본 개념



  • Convolution 연산





Padding

출력 크기를 조정할 목적으로 사용하는 방법이다. 입력데이터가 합성곱 연산을 거치면 출력의 크기가 작아지기 때문에, 깊은 신경망의 경우 어느 시점에서는 출력의 크기가 1이 되어버리는 문제가 발생해 더 이상 합성곱 적용이 불가능해지는 문제가 있다. 출력 크기를 입력과 같은 크기가 되도록 하는 것을 패딩이라 한다.

  • 폭이 1인 패딩의 예


Stride

필터를 적용하는 위치의 간격을 의미한다.



3차원 데이터의 합성곱 연산
















Pooling

  • 가로 세로 방향의 공간을 줄이는 연산

  • 이미지 인식 분야에서는 주로 최대 풀링 사용 (c.f. 평균 풀링)

  • 윈도우 크기와 스트라이드는 같은 값으로 설정

  • 윈도우 크기 = 2*2, 스트라이드 = 2 인 최대 풀링의 예
















CNN 전체 흐름




3.2 Why CNN?

  • 가중치 공유를 통해 학습 대상 가중치의 개수가 현저히 감소

  • 다중 feature맵 추출

  • 공간 정보 활용

  • Stride 크기를 이용한 다운샘플링

  • 텐서에 적용하기 용이

  • 가변 크기의 입력데이터를 다루는 것이 가능

3.3 CNN 사례

  • LeNet-5

    • LeCun이 1990년대에 제안한 초창기 CNN

    • C-P-C-P-C의 다섯 층을 이용해 feature map 추출

    • 마지막 단에 fully-connected network & softmax 로 마무리

  • AlexNet

    • Krizhevsky, 2012

    • 컨볼루션 층 5개와 FC 층 3개로 구성

    • 입력: 224 * 224의 RGB 3채널 영상 (3 * 224 * 224)

    • C층: 96 filters with 3 * 11 * 11

    • FC층: 6,500만 개 parameter

  • VGGNet

    • Simonyan, 2016

    • 필터 크기를 줄이고 대신 신경망을 깊게 만들어 model parameter 개수를 줄임

    • 공개버전: VGG-16, VGG-19

  • GoogleNet

    • Szegedy, 2015, 2016

    • NIN (network in network, Lin, 2014) 아이디어를 수정한 인셉션 모듈을 사용

    • 네 종류의 컨볼루션 연산을 수행하고 결과를 종합하는 방식

  • ResNet

    • He, 2016

    • 깊은 층을 추구하지만 층이 너무 많은 경우 오히려 성능이 저하되는 현상이 나타나는 문제를 해결 (그래디언트 소멸 등)

    • Building block: C층 2개로 \(F({\mathbf x}) = \tau({\mathbf x} w_1) w_2\)을 학습(residual), \(y = \tau(F(x) + x)\)

    • Building block 여러 개를 쌓아 깊이를 더 깊게…

3.3 Example: MNIST 데이터

library(keras)

mnist <- dataset_mnist()
c(c(train_images, train_labels), c(test_images, test_labels)) %<-% mnist

train_images <- array_reshape(train_images, c(60000, 28, 28, 1))
train_images <- train_images / 255

test_images <- array_reshape(test_images, c(10000, 28, 28, 1))
test_images <- test_images / 255

train_labels <- to_categorical(train_labels)
test_labels <- to_categorical(test_labels)

model <- keras_model_sequential() %>%
  layer_conv_2d(filters = 32, 
                kernel_size = c(3, 3), 
                activation = "relu",
                input_shape = c(28, 28, 1)) %>%
  layer_max_pooling_2d(pool_size = c(2, 2)) %>%
  layer_conv_2d(filters = 64, 
                kernel_size = c(3, 3), 
                activation = "relu") %>%
  layer_max_pooling_2d(pool_size = c(2, 2)) %>%
  layer_conv_2d(filters = 64, 
                kernel_size = c(3, 3), 
                activation = "relu")

summary(model)
Model: "sequential_1"
___________________________________________________________________________
Layer (type)                     Output Shape                  Param #     
===========================================================================
conv2d (Conv2D)                  (None, 26, 26, 32)            320         
___________________________________________________________________________
max_pooling2d (MaxPooling2D)     (None, 13, 13, 32)            0           
___________________________________________________________________________
conv2d_1 (Conv2D)                (None, 11, 11, 64)            18496       
___________________________________________________________________________
max_pooling2d_1 (MaxPooling2D)   (None, 5, 5, 64)              0           
___________________________________________________________________________
conv2d_2 (Conv2D)                (None, 3, 3, 64)              36928       
===========================================================================
Total params: 55,744
Trainable params: 55,744
Non-trainable params: 0
___________________________________________________________________________
model <- model %>%
  layer_flatten() %>%
  layer_dense(units = 64, activation = "relu") %>%
  layer_dense(units = 10, activation = "softmax")

model %>% compile(
  optimizer = "adam",
  loss = "categorical_crossentropy",
  metrics = c("accuracy")
)

model %>% fit(
  train_images, train_labels,
  epochs = 5, batch_size = 100
)

model %>% evaluate(test_images, test_labels)
$loss
[1] 0.03172737519

$acc
[1] 0.9900000095
pred <- model %>% predict_classes(test_images)
actual <- apply(test_labels, 1, which.max) - 1
table(actual, pred)
      pred
actual    0    1    2    3    4    5    6    7    8    9
     0  967    0    3    0    0    3    3    3    1    0
     1    0 1113    0    3    2    0    1    6   10    0
     2    0    0 1026    0    0    0    0    6    0    0
     3    0    0    1 1004    0    0    0    2    3    0
     4    0    0    0    0  979    0    0    0    0    3
     5    0    0    0    8    0  883    1    0    0    0
     6    2    3    0    0    3    4  944    0    2    0
 [ reached getOption("max.print") -- omitted 3 rows ]

4. Recurrent Neural Network

4.1 구조

  • 순차데이터에 feed-forward 신경망을 사용하기 어려운 이유

    • Feed-forward networks have no memory, i.e., each input is processed independently

    • Hence, in order to process a sequential data, we have to show the entire sequence to the network at once

  • 순차데이터 처리를 위한 신경망이 갖추기 바라는 기능

    • 시간성: feature를 순서대로 하나씩 입력할 수 있어야 함

    • 가변길이: 길이가 \(T\)인 샘플을 처리하려면 \(T\)개의 hidden layer가 필요한데, \(T\)는 가변적일 수 있어야 함

    • 문맥의존성: 이전 특징 내용을 기억하고 있다가 필요한 순간에 적절히 활용할 수 있어야 함

  • RNN(recurrent neural network)의 구조

    • \(t\)시점에 해당하는 hidden node와 출력은 다음과 같이 구축 \[ {\mathbf h}(t) = f({\mathbf U}{\mathbf h}(t-1) + {\mathbf V}{\mathbf x}(t)),\quad {\mathbf y}(t) = g({\mathbf W}{\mathbf h}(t)) \] 이 때 \(\boldsymbol\Theta = ({\mathbf U}, {\mathbf V}, {\mathbf W})\)는 시간에 대해 불변임에 유의


  • 모든 시점에서 가중치 \(\boldsymbol\Theta\)를 공유하기 때문에

    • 학습 대상 parameter의 개수가 입력 데이터의 길이 \(T\)와 무관

    • Feature가 입력되는 순서가 다소 달라지더라도 같거나 유사한 출력값을 얻음

  • 위 구조식에 의하면 기본적으로 매 시점에서 입력과 출력이 있지만 꼭 그럴 필요는 없음

    • (예) STT 데이터를 읽고 ’고객이 현재 가입 중인 통신사와 상품 카테고리는?’이라는 질문에 대해 ’LGU+, 모바일’이라는 답을 찾아야 하는 경우는 맨 마지막에 한 번만 출력을 내놓는 경우에 해당

4.2 학습

  • 기본적으로 stochastic gradient descent 알고리즘 사용

    • 목적함수 \[ J(\boldsymbol\Theta) = \sum_{t=1}^T J^{(t)}(\boldsymbol\Theta) \] 단, \(J^{(t)}\)\(t\) 시점에서 출력과 실제 \(y\)값을 이용해 계산한 오차 (mse, cross-entropy, log-likelihood 등)
  • 그러나 시간성 구조 때문에 feed-forward 모형처럼 SGD에 error backpropagation 알고리즘을 바로 적용하기 어려움

  • 소위 BPTT(backpropagation through time) 알고리즘을 이용해 solution을 구함

  • 그래디언트 소멸/폭발 문제

    • \(T\)가 큰 경우, \(\boldsymbol U\)의 성분값이 1보다 작으면 그래디언트 소멸, 반대의 경우 그래디언트 폭발 문제 발생

    • 해결방안으로 LSTM이 널리 사용됨


4.3 실습 - IMDB data

  • Preparing IMDB data
# library(tensorflow)
# install_tensorflow(version = "nightly")

library(keras)

max_features <- 10000 # Number of words to consider as features
maxlen <- 120 # Cuts off texts after this many words 

imdb <- dataset_imdb(num_words = max_features)

c(c(x_train, y_train), c(x_test, y_test)) %<-% imdb

cat(length(x_train), "train sequences\n")
25000 train sequences
cat(length(x_test), "test sequences")
25000 test sequences
cat("Pad sequences (samples x time)\n")
Pad sequences (samples x time)
x_train <- pad_sequences(x_train, maxlen = maxlen)
x_test <- pad_sequences(x_test, maxlen = maxlen)
cat("x_train shape:", dim(x_train), "\n")
x_train shape: 25000 120 
cat("x_test shape:", dim(x_test), "\n")
x_test shape: 25000 120 
  • Embedding and classification by a feed-forward network
library(keras)

model <- keras_model_sequential() %>%
  layer_embedding(input_dim = max_features,
                  output_dim = 256,
                  input_length = maxlen) %>%
  layer_flatten() %>%
  layer_dense(units = 32, activation = "relu") %>%
  layer_dense(units = 1, activation = "sigmoid")

model %>% compile(
  optimizer = "rmsprop",
  loss = "binary_crossentropy",
  metrics = c("accuracy")
)

summary(model)
Model: "sequential_2"
___________________________________________________________________________
Layer (type)                     Output Shape                  Param #     
===========================================================================
embedding (Embedding)            (None, 120, 256)              2560000     
___________________________________________________________________________
flatten_1 (Flatten)              (None, 30720)                 0           
___________________________________________________________________________
dense_5 (Dense)                  (None, 32)                    983072      
___________________________________________________________________________
dense_6 (Dense)                  (None, 1)                     33          
===========================================================================
Total params: 3,543,105
Trainable params: 3,543,105
Non-trainable params: 0
___________________________________________________________________________
history <- model %>% fit(
  x_train, y_train,
  epochs = 10,
  batch_size = 100,
  validation_split = 0.2
)
plot(history)

model %>% evaluate(x_test, y_test)
$loss
[1] 1.072044177

$acc
[1] 0.8331199884
prob <- model %>% predict_proba(x_test)
Predicted <- model %>% predict_classes(x_test)
table(Predicted = Predicted, Actual = y_test)
         Actual
Predicted     0     1
        0 10318  1990
        1  2182 10510

Simple RNN

library(keras)

model <- keras_model_sequential() %>%
  layer_embedding(input_dim = max_features, 
                  output_dim = 256) %>%
  layer_simple_rnn(units = 64) %>%
  layer_dense(units = 1, activation = "sigmoid")

summary(model)
Model: "sequential_3"
___________________________________________________________________________
Layer (type)                     Output Shape                  Param #     
===========================================================================
embedding_1 (Embedding)          (None, None, 256)             2560000     
___________________________________________________________________________
simple_rnn (SimpleRNN)           (None, 64)                    20544       
___________________________________________________________________________
dense_7 (Dense)                  (None, 1)                     65          
===========================================================================
Total params: 2,580,609
Trainable params: 2,580,609
Non-trainable params: 0
___________________________________________________________________________
model %>% compile(
  optimizer = "rmsprop",
  loss = "binary_crossentropy",
  metrics = c("acc")
  )

history <- model %>% fit(
  x_train, y_train,
  epochs = 10,
  batch_size = 100,
  validation_split = 0.2
)
plot(history)

model %>% evaluate(x_test, y_test)
$loss
[1] 1.009598777

$acc
[1] 0.7644799948
prob <- model %>% predict_proba(x_test)
Predicted <- model %>% predict_classes(x_test)
table(Predicted = Predicted, Actual = y_test)
         Actual
Predicted    0    1
        0 9952 3340
        1 2548 9160

RNN: LSTM

library(keras)

model <- keras_model_sequential() %>%
  layer_embedding(input_dim = max_features, 
                  output_dim = 256) %>%
  layer_lstm(units = 64) %>%
  layer_dense(units = 1, activation = "sigmoid")

summary(model)
Model: "sequential_4"
___________________________________________________________________________
Layer (type)                     Output Shape                  Param #     
===========================================================================
embedding_2 (Embedding)          (None, None, 256)             2560000     
___________________________________________________________________________
lstm (LSTM)                      (None, 64)                    82176       
___________________________________________________________________________
dense_8 (Dense)                  (None, 1)                     65          
===========================================================================
Total params: 2,642,241
Trainable params: 2,642,241
Non-trainable params: 0
___________________________________________________________________________
model %>% compile(
  optimizer = "rmsprop",
  loss = "binary_crossentropy",
  metrics = c("acc")
  )

history <- model %>% fit(
  x_train, y_train,
  epochs = 10,
  batch_size = 100,
  validation_split = 0.2
)
plot(history)

model %>% evaluate(x_test, y_test)
$loss
[1] 0.5473123718

$acc
[1] 0.8357599974
prob <- model %>% predict_proba(x_test)
Predicted <- model %>% predict_classes(x_test)
table(Predicted = Predicted, Actual = y_test)
         Actual
Predicted     0     1
        0 10053  1659
        1  2447 10841

1d CNN

library(keras)

model <- keras_model_sequential() %>%
  layer_embedding(input_dim = max_features, 
                  output_dim = 256,
                  input_length = maxlen) %>%
  layer_conv_1d(filters = 32,
                kernel_size = 5, 
                activation = "relu") %>%
  layer_max_pooling_1d(pool_size = 4) %>%
  layer_conv_1d(filters = 32,
                kernel_size = 5, 
                activation = "relu") %>%
  layer_max_pooling_1d(pool_size = 4) %>%
  layer_conv_1d(filters = 32, 
                kernel_size = 3, 
                activation = "relu") %>%
  layer_global_max_pooling_1d() %>%
  layer_dropout(rate = 0.5) %>%
  layer_dense(units = 16, activation = "sigmoid") %>%
  #layer_dropout(rate = 0.5) %>% 
  #layer_dense(units = 8, activation = "sigmoid") %>%
  layer_dense(units = 1, activation = "sigmoid")

summary(model)
Model: "sequential_5"
___________________________________________________________________________
Layer (type)                     Output Shape                  Param #     
===========================================================================
embedding_3 (Embedding)          (None, 120, 256)              2560000     
___________________________________________________________________________
conv1d (Conv1D)                  (None, 116, 32)               40992       
___________________________________________________________________________
max_pooling1d (MaxPooling1D)     (None, 29, 32)                0           
___________________________________________________________________________
conv1d_1 (Conv1D)                (None, 25, 32)                5152        
___________________________________________________________________________
max_pooling1d_1 (MaxPooling1D)   (None, 6, 32)                 0           
___________________________________________________________________________
conv1d_2 (Conv1D)                (None, 4, 32)                 3104        
___________________________________________________________________________
global_max_pooling1d (GlobalMaxP (None, 32)                    0           
___________________________________________________________________________
dropout_2 (Dropout)              (None, 32)                    0           
___________________________________________________________________________
dense_9 (Dense)                  (None, 16)                    528         
___________________________________________________________________________
dense_10 (Dense)                 (None, 1)                     17          
===========================================================================
Total params: 2,609,793
Trainable params: 2,609,793
Non-trainable params: 0
___________________________________________________________________________
model %>% compile(
  optimizer = optimizer_rmsprop(lr = 1e-4),
  loss = "binary_crossentropy",
  metrics = c("acc")
  )

history <- model %>% fit(
  x_train, y_train,
  epochs = 12,
  batch_size = 100,
  validation_split = 0.2
)

plot(history)

model %>% evaluate(x_test, y_test)
$loss
[1] 0.4172768436

$acc
[1] 0.8238800168
prob <- model %>% predict_proba(x_test)
Predicted <- model %>% predict_classes(x_test)
table(Predicted = Predicted, Actual = y_test)
         Actual
Predicted     0     1
        0 10230  2133
        1  2270 10367

Bidirectional RNN

library(keras)

model <- keras_model_sequential() %>%
  layer_embedding(input_dim = max_features, output_dim = 256) %>%
  bidirectional(
    layer_lstm(units = 64)
    ) %>%
  layer_dense(units = 1, activation = "sigmoid")

summary(model)
Model: "sequential_6"
___________________________________________________________________________
Layer (type)                     Output Shape                  Param #     
===========================================================================
embedding_4 (Embedding)          (None, None, 256)             2560000     
___________________________________________________________________________
bidirectional (Bidirectional)    (None, 128)                   164352      
___________________________________________________________________________
dense_11 (Dense)                 (None, 1)                     129         
===========================================================================
Total params: 2,724,481
Trainable params: 2,724,481
Non-trainable params: 0
___________________________________________________________________________
model %>% compile(
  optimizer = "adam", #optimizer_rmsprop(lr = 1e-4),
  loss = "binary_crossentropy",
  metrics = c("acc")
  )

history <- model %>% fit(
  x_train, y_train,
  epochs = 10,
  batch_size = 100,
  validation_split = 0.2
)

plot(history)

model %>% evaluate(x_test, y_test)
$loss
[1] 0.8859894094

$acc
[1] 0.8222000003
prob <- model %>% predict_proba(x_test)
Predicted <- model %>% predict_classes(x_test)
table(Predicted = Predicted, Actual = y_test)
         Actual
Predicted     0     1
        0 11078  3023
        1  1422  9477